package cn.topevery.garden.wapi.service;


import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.topevery.sdk.common.properties.RunBaseProperties;
import com.topevery.sdk.common.util.RsaUtil;
import com.topevery.sdk.sync.query.BaseQuery;
import com.topevery.sdk.sync.service.ISyncDataHandle;
import com.topevery.sdk.sync.vo.*;
import com.topevery.sdk.sync.web.DataPager;
import hw.topevery.basis.dal.logic.SysDeptLogic;
import hw.topevery.basis.dal.logic.SysUserInDeptLogic;
import hw.topevery.basis.dal.logic.SysUserInRoleLogic;
import hw.topevery.basis.dal.logic.SysUserLogic;
import hw.topevery.basis.entity.dto.DeptDto;
import hw.topevery.basis.entity.dto.SysUserDto;
import hw.topevery.basis.entity.fetch.DeptFetch;
import hw.topevery.basis.entity.fetch.UserFetch;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class SyncDataService implements ISyncDataHandle {

    @Autowired
    SysUserLogic sysUserLogic;

    @Autowired
    SysDeptLogic sysDeptLogic;

    @Autowired
    SysUserInRoleLogic sysUserInRoleLogic;

    @Autowired
    SysUserInDeptLogic sysUserInDeptLogic;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    ObjectMapper objectMapper;

//    @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
    public String oauthUrl;

//    @Value("${topevery.authUrl}")
    private String authUrl;

    @Override

    public DataPager<OpenUserVO> getUsers(BaseQuery query, RunBaseProperties properties) {
        UserFetch para = new UserFetch();
        para.setPageIndex(query.getPageIndex());
        para.setPageSize(query.getPageSize());
        hw.topevery.framework.db.entity.DataPager<SysUserDto> dataPager = sysUserLogic.getUserList(para);
        List<OpenUserVO> openUserVOList = dataPager.records.stream().map(sysUser -> {
            OpenUserVO openUserVO = new OpenUserVO();
            openUserVO.setUserId(sysUser.userId);
            openUserVO.setUserName(sysUser.userName);
            openUserVO.setLoginName(sysUser.loginName);
            openUserVO.setDeptId(sysUser.deptId);
            openUserVO.setDeptName(sysUser.getDeptName());
            openUserVO.setMobile(sysUser.userMobile);
            openUserVO.setEmail(sysUser.userEmail);
            openUserVO.setState(String.valueOf(sysUser.userStatus));
            return openUserVO;
        }).collect(Collectors.toList());
        DataPager<OpenUserVO> page = new DataPager<>();
        page.setRecords(openUserVOList);
        page.setTotal(dataPager.total);
        return page;
    }

    @Override
    public DataPager<OpenDeptVO> getDepts(BaseQuery query, RunBaseProperties properties) {
        DeptFetch fetch = new DeptFetch();
        fetch.setPageIndex(query.getPageIndex());
        fetch.setPageSize(query.getPageSize());
        hw.topevery.framework.db.entity.DataPager<DeptDto> dataPager = sysDeptLogic.getList(fetch);
        List<OpenDeptVO> openDeptVOList = dataPager.records.stream().map(dept -> {
            OpenDeptVO openDept = new OpenDeptVO();
            openDept.setDeptId(dept.deptId);
            openDept.setDeptCode(dept.deptCode);
            openDept.setDeptName(dept.deptName);
            openDept.setDeptPid(dept.deptPid);
            openDept.setState(String.valueOf(dept.deptStatus));
            return openDept;
        }).collect(Collectors.toList());
        DataPager<OpenDeptVO> page = new DataPager<>();
        page.setTotal(dataPager.total);
        page.setRecords(openDeptVOList);
        return page;
    }

    @Override
    public DataPager<OpenMenuVO> getMenus(BaseQuery query, RunBaseProperties properties) {
        DataPager<OpenMenuVO> page = new DataPager<>();
        page.setTotal(0);
        page.setRecords(Collections.emptyList());
        return page;
    }

    @Override
    public DataPager<OpenRoleVO> getRoles(BaseQuery query, RunBaseProperties properties) {
        DataPager<OpenRoleVO> page = new DataPager<>();
        page.setTotal(0);
        page.setRecords(Collections.emptyList());
        return page;
    }

    @Override
    public DataPager<OpenUserInDeptVO> getUserInDepts(BaseQuery query, RunBaseProperties properties) {
   /*     List<OpenUserInDeptVO> openUserInDeptVOList = sysUserInDeptLogic.get().stream().map(userInDept -> {
            OpenUserInDeptVO openUserInDept = new OpenUserInDeptVO();
            openUserInDept.setUserId(userInDept.userId);
            openUserInDept.setDeptId(userInDept.deptId);
            return openUserInDept;
        }).collect(Collectors.toList());*/
        DataPager<OpenUserInDeptVO> page = new DataPager<>();
      /*  page.setTotal(openUserInDeptVOList.size());
        page.setRecords(openUserInDeptVOList);*/
        return page;
    }

    @Override
    public DataPager<OpenUserInRoleVO> getUserInRoles(BaseQuery query, RunBaseProperties properties) {
        /*List<OpenUserInRoleVO> allList = sysUserInRoleLogic.getAllList().stream().map(userInRole -> {
            OpenUserInRoleVO openUserInRole = new OpenUserInRoleVO();
            openUserInRole.setUserId(userInRole.userId);
            openUserInRole.setRoleId(userInRole.roleId);
            return openUserInRole;
        }).collect(Collectors.toList());*/
        DataPager<OpenUserInRoleVO> page = new DataPager<>();
      /*  page.setTotal(allList.size());
        page.setRecords(allList);*/
        return page;
    }

    @Override
    public DataPager<OpenUserInMenuVO> getUserInMenus(BaseQuery query, RunBaseProperties properties) {
        DataPager<OpenUserInMenuVO> page = new DataPager<>();
        page.setTotal(0);
        page.setRecords(Collections.emptyList());
        return page;
    }

    @Override
    public DataPager<OpenMenuInRoleVO> getMenuInRoles(BaseQuery query, RunBaseProperties properties) {
        DataPager<OpenUserInRoleVO> page = new DataPager<>();
        page.setTotal(0);
        page.setRecords(Collections.emptyList());
        return null;
    }


    @SneakyThrows
    @Override
    public OpenTokenVO loginByToken(String token, RunBaseProperties properties) {
        String openToken = RsaUtil.decryptByPublicKey(token, properties.getRsaPublicKey());
        JWT jwt = JWTUtil.parseToken(openToken);
        String loginName = (String) jwt.getPayload("sub");
        if (StringUtils.isNotEmpty(loginName)) {
            Map<String, Object> tokenBody = tokenFromOauthServer(loginName);
            if (CollectionUtils.isEmpty(tokenBody)) {
                throw new RuntimeException("token静默登录失败");
            }
            OpenTokenVO openTokenVO = new OpenTokenVO();
            openTokenVO.setAccess_token(String.valueOf(tokenBody.get("access_token")));
            openTokenVO.setRefresh_token(String.valueOf(tokenBody.get("refresh_token")));
            openTokenVO.setToken_type(String.valueOf(tokenBody.get("token_type")));
            openTokenVO.setScope(String.valueOf(tokenBody.get("scope")));
            openTokenVO.setExpires_in((Integer) tokenBody.get("expires_in"));
            return openTokenVO;
        } else {
            throw new RuntimeException("token静默登录失败!");
        }
    }

    private Map<String, Object> tokenFromOauthServer(String username) {
        HttpHeaders headers = new HttpHeaders();
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        // 数据库里Oauth客户端表里的记录可能会被重置，所以新建一条记录。
        map.put("grant_type", Collections.singletonList("username"));
        map.put("client_id", Collections.singletonList("api-resource2"));
        map.put("client_secret", Collections.singletonList("api#resource#123"));
        map.put("username", Collections.singletonList(username));
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(map, headers);
    /*    ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(oauthUrl + "/oauth2/token", HttpMethod.POST, httpEntity, new ParameterizedTypeReference<Map<String, Object>>() {
        });*/
        return null;
    }
}
